﻿// RuntimeSerializationSurrogate.cs
//
// Copyright 2008 by Burt Harris
// Licensed under the Microsoft Public License (Ms-PL)
// See: http://www.codeplex.com/yaml/license
//
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.Serialization;

namespace YaTools.Yaml.Serialization
{
    using System.Text.RegularExpressions;
    using YaTools.Yaml;

    [DebuggerDisplay("RuntimeSerializationSurrogate({_type.Name})")]
    [Obsolete]
    class RuntimeSerializationSurrogate : YamlSurrogate
    {
        static Uri s_baseUri = new Uri("tag:yatools.net,2009:rs,");
        private Type _type;
        private MemberInfo[] serializableMembers;
        private string[] names;
        
        /// <summary>
        /// Return the base URI for tags handled by this surrogate.
        /// </summary>
        protected override Uri BaseUri
        {
            get { return s_baseUri; }
        }

        static readonly Regex backingFieldPattern
            = new Regex("\\<(.+)\\>k__BackingField");

        internal RuntimeSerializationSurrogate(Type t)
        {
            this._type = t;
            this.serializableMembers = FormatterServices.GetSerializableMembers(t);
            this.names = new string[serializableMembers.Length];

            for (int i=0; i<serializableMembers.Length; i++)
            {
                var member = serializableMembers[i];
                names[i] = member.Name;

                if (member.MemberType == MemberTypes.Field)
                {
                    Match match = backingFieldPattern.Match(member.Name);
                    if (match.Success)
                        names[i] = match.Groups[1].Value;
                }
            }
        }

        public override void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
        {
            var writer = context.YamlWriter();
            var objref = __makeref(obj);

            if (writer.BeginMap(obj, GetUri(obj.GetType()), false))
            {
                try
                {
                    for (int i=0; i<serializableMembers.Length; i++)
                    {
                        MemberInfo member = serializableMembers[i];

                        writer.WriteKey(names[i], Globals.TypeOfString);
                        switch (member.MemberType)
                        {
                            case MemberTypes.Field:
                                var field = (FieldInfo)member;
                                writer.WriteItem( field.GetValueDirect(objref), 
                                                  field.FieldType );
                                break;
                            case MemberTypes.Property:
                                var property = (PropertyInfo)member;
                                writer.WriteItem( property.GetValue(obj, null),
                                                  property.PropertyType );
                                break;
                        }
                    }
                }
                finally
                {
                    writer.EndMap();
                }
            }
        }

        public override object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
        {
            return null;
        }

    }
}
